package nio;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SocketChannel;

import config.Config;
import crono.Cronometro;

public class FileNetSenderNIO {
	public static void main(String[] args) throws IOException {
		Cronometro timer = new Cronometro();
		timer.start();

		boolean done = false;

		System.out.printf("Attemping to connect to host %s on port %d.\n",
				Config.NET_SERVER_IP, Config.NET_SERVER_PORT);

		try (SocketChannel clientSocketChannel = SocketChannel.open();
				FileInputStream fileInputStream = new FileInputStream(new File(
						Config.INPUT_FILE));
				FileChannel fileChannel = fileInputStream.getChannel();) {
			clientSocketChannel.bind(new InetSocketAddress(
					Config.NET_CLIENT_IP, Config.NET_CLIENT_PORT));
			clientSocketChannel.connect(new InetSocketAddress(
					Config.NET_SERVER_IP, Config.NET_SERVER_PORT));
			clientSocketChannel.configureBlocking(false);

			int size = Integer.MAX_VALUE;

			ByteBuffer buf = ByteBuffer.allocate(Config.NET_BUF_SIZE);

			while (size >= 0) {
				buf.clear();
				size = fileChannel.read(buf);
				buf.flip();
				while (buf.hasRemaining()) {
					clientSocketChannel.write(buf);
				}
			}

			System.out.println("Data has been sent. Waiting for ACK...");

			ByteBuffer ackBuffer = ByteBuffer.allocate(1);
			ackBuffer.clear();
			while (ackBuffer.position() == 0) {
				clientSocketChannel.read(ackBuffer);
			}
			ackBuffer.flip();
			if (ackBuffer.get() == Config.TX_ACK_BYTE) {
				System.out.println("ACK received. TX verified.");
				done = true;
			} else {
				System.out.println("Unknown ACK received. TX NOT verified.");
			}
		} catch (RuntimeException e) {
			System.err.println("Exception: " + e);
		}

		if (done) {
			timer.stop();
			timer.print("NIO. Copy file over network");
		}
	}
}